home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / misc / amigem.lha / amigem / exec / semaphores.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-19  |  5.7 KB  |  234 lines

  1. #include <exec/execbase.h>
  2. #include <exec/memory.h>
  3. #include <exec/semaphores.h>
  4. #include <exec/devices.h>
  5. #include <exec/io.h>
  6. #include <clib/_exec.h>
  7.  
  8. #define SEMAPHORESIGF (0x8000)
  9.  
  10. #define SM_TYPE_OBTAIN    0
  11. #define SM_TYPE_PROCURE    1
  12.  
  13. #include <amigem/fd_lib.h>
  14. #define LIBBASE struct ExecBase *SysBase
  15.  
  16. FD1(93,VOID,InitSemaphore,struct SignalSemaphore *sem,A0)
  17.   sem->ss_WaitQueue.mlh_Head    =(struct MinNode *)&sem->ss_WaitQueue.mlh_Tail;
  18.   sem->ss_WaitQueue.mlh_Tail    =NULL;
  19.   sem->ss_WaitQueue.mlh_TailPred=(struct MinNode *)&sem->ss_WaitQueue.mlh_Head;
  20.   sem->ss_NestCount=0;
  21. }
  22.  
  23. FD1(94,VOID,ObtainSemaphore,struct SignalSemaphore *sem,A0)
  24. {
  25.   struct Task *me;
  26.   me=FindTask(NULL);
  27.   Forbid();
  28.     if(sem->ss_NestCount&&sem->ss_Owner!=me)
  29.     {
  30.       struct Message sm;
  31.       sm.mn_ReplyPort=(struct MsgPort *)me;
  32.       sm.mn_Node.ln_Type=SM_TYPE_OBTAIN;
  33.       sm.mn_Node.ln_Name=(char *)SM_EXCLUSIVE;
  34.       AddTail((struct List *)&sem->ss_WaitQueue,&sm.mn_Node);
  35.       Wait(SEMAPHORESIGF);
  36.     }
  37.     else
  38.       sem->ss_NestCount++;
  39.   Permit();
  40.  
  41. FD1(96,ULONG,AttemptSemaphore,struct SignalSemaphore *sem,A0)
  42. {
  43.   LONG ret=0;
  44.   struct Task *me;
  45.   me=FindTask(NULL);
  46.   Forbid();
  47.     if(!sem->ss_NestCount||sem->ss_Owner==me)
  48.     {
  49.       ObtainSemaphore(sem);
  50.       ret=1;
  51.     }
  52.   Permit();
  53.   return ret;
  54.     
  55. FD1(113,VOID,ObtainSemaphoreShared,struct SignalSemaphore *sem,A0)
  56. {
  57.   struct Task *me;
  58.   me=FindTask(NULL);
  59.   Forbid();
  60.     if(sem->ss_NestCount>0)
  61.     {
  62.       if(sem->ss_Owner!=me)
  63.       { 
  64.         struct Message sm;
  65.         sm.mn_ReplyPort=(struct MsgPort *)me;
  66.         sm.mn_Node.ln_Type=SM_TYPE_OBTAIN;
  67.         sm.mn_Node.ln_Name=(char *)SM_SHARED;
  68.         AddTail((struct List *)&sem->ss_WaitQueue,&sm.mn_Node);
  69.         Wait(SEMAPHORESIGF);
  70.       }
  71.       else
  72.         sem->ss_NestCount++;
  73.     }
  74.     else
  75.       sem->ss_NestCount--;
  76.   Permit();
  77.  
  78. FD1(120,ULONG,AttemptSemaphoreShared,struct SignalSemaphore *sem,A0)
  79. {
  80.   LONG ret=0;
  81.   struct Task *me;
  82.   me=FindTask(NULL);
  83.   Forbid();
  84.     if(sem->ss_NestCount<=0||sem->ss_Owner==me)
  85.     {
  86.       ObtainSemaphoreShared(sem);
  87.       ret=1;
  88.     }
  89.   Permit();
  90.   return ret;
  91.  
  92. FD1(95,VOID,ReleaseSemaphore,struct SignalSemaphore *sem,A0)
  93.   Forbid();
  94.     if(sem->ss_NestCount>0) /* I hold an exclusive lock */
  95.       sem->ss_NestCount--;
  96.     else                    /* A shared lock */
  97.       sem->ss_NestCount++;
  98.     if(!sem->ss_NestCount&&sem->ss_WaitQueue.mlh_Head->mln_Succ!=NULL)
  99.     { 
  100.       struct SemaphoreMessage *sm;
  101.       sm=(struct SemaphoreMessage *)sem->ss_WaitQueue.mlh_Head;
  102.       if(sm->ssm_Message.mn_Node.ln_Name!=(char *)SM_EXCLUSIVE)
  103.       { 
  104.         struct MinNode *mn;
  105.         mn=(struct MinNode *)sm;
  106.         while(mn->mln_Succ!=NULL)
  107.         { 
  108.           sm=(struct SemaphoreMessage *)mn;
  109.           mn=mn->mln_Succ;
  110.           if(sm->ssm_Message.mn_Node.ln_Type!=SM_EXCLUSIVE)
  111.           { 
  112.             Remove((struct Node *)sm);
  113.             if(sm->ssm_Message.mn_Node.ln_Type==SM_TYPE_OBTAIN)
  114.               Signal((struct Task *)sm->ssm_Message.mn_ReplyPort,SEMAPHORESIGF);
  115.             else
  116.               ReplyMsg(&sm->ssm_Message);
  117.             sem->ss_NestCount--;
  118.           }
  119.           sem->ss_Owner=NULL;
  120.         }
  121.       }
  122.       else
  123.       { 
  124.         Remove((struct Node *)sm);
  125.         if(sm->ssm_Message.mn_Node.ln_Type==SM_TYPE_OBTAIN)
  126.         {
  127.           sem->ss_Owner=(struct Task *)sm->ssm_Message.mn_ReplyPort;
  128.           Signal((struct Task *)sm->ssm_Message.mn_ReplyPort,SEMAPHORESIGF);
  129.         }
  130.         else
  131.         {
  132.           sem->ss_Owner=(struct Task *)&sm->ssm_Message.mn_ReplyPort->mp_SigTask;
  133.           ReplyMsg(&sm->ssm_Message);
  134.         }
  135.         sem->ss_NestCount++;
  136.       }
  137.     }
  138.   Permit();
  139. }
  140.  
  141. FD2(90,VOID,Procure,struct SignalSemaphore *sem,A0,struct SemaphoreMessage *sm,A1)
  142. {
  143.   sm->ssm_Message.mn_Length=sizeof(struct SemaphoreMessage);
  144.   Forbid();
  145.     if((ULONG)sm->ssm_Message.mn_Node.ln_Name==SM_SHARED?
  146.        AttemptSemaphoreShared(sem):AttemptSemaphore(sem))
  147.     {
  148.       sm->ssm_Semaphore=sem;
  149.       ReplyMsg(&sm->ssm_Message);
  150.     }
  151.     else
  152.       AddTail((struct List *)&sem->ss_WaitQueue,&sm->ssm_Message.mn_Node);
  153.   Permit();
  154. }
  155.  
  156. FD2(91,VOID,Vacate,struct SignalSemaphore *sem,A0,struct SemaphoreMessage *sm,A1)
  157. {
  158.   struct MinNode *mn;
  159.   Forbid();
  160.     mn=(struct MinNode *)sem->ss_WaitQueue.mlh_Head;
  161.     while(mn->mln_Succ!=NULL)
  162.     { 
  163.       if(sm==(struct SemaphoreMessage *)mn)
  164.       {
  165.         Remove((struct Node *)mn);
  166.         ReplyMsg(&sm->ssm_Message);
  167.         break;
  168.       }
  169.       mn=mn->mln_Succ;
  170.     }
  171.     if(mn->mln_Succ==NULL)
  172.       ReleaseSemaphore(sem);
  173.   Permit();
  174.   sm->ssm_Semaphore=NULL;
  175. }
  176.  
  177. /*
  178.  * It would be nice if we could use the ss_MultipleLink to arbitrate
  179.  * for all semaphores at once but the message semaphore mechanism
  180.  * won't let us do it :(
  181.  *
  182.  * There's no problem with it though since other tasks will have to
  183.  * arbitrate for the list in the same order we do. So the first
  184.  * semaphore in the list arbitrates for the whole list.
  185.  */
  186. FD1(97,VOID,ObtainSemaphoreList,struct List *sl,A0)
  187. {
  188.   struct Node *n;
  189.   n=sl->lh_Head;
  190.   while(n->ln_Succ!=NULL)
  191.   {
  192.     ObtainSemaphore((struct SignalSemaphore *)n);
  193.     n=n->ln_Succ;
  194.   }
  195. }
  196.  
  197. FD1(98,VOID,ReleaseSemaphoreList,struct List *sl,A0)
  198. {
  199.   struct Node *n;
  200.   n=sl->lh_Head;
  201.   while(n->ln_Succ!=NULL)
  202.   {
  203.     ReleaseSemaphore((struct SignalSemaphore *)n);
  204.     n=n->ln_Succ;
  205.   }
  206. }
  207.  
  208. FD1(100,VOID,AddSemaphore,struct SignalSemaphore *sem,A1)
  209. {
  210.   sem->ss_Link.ln_Type=NT_SIGNALSEM;
  211.   InitSemaphore(sem);
  212.   Forbid();
  213.     Enqueue(&SysBase->SemaphoreList,&sem->ss_Link);
  214.   Permit();
  215. }
  216.  
  217. FD1(101,VOID,RemSemaphore,struct SignalSemaphore *sem,A1)
  218. {
  219.   Forbid();
  220.     Remove(&sem->ss_Link);
  221.   Permit();
  222. }
  223.  
  224. FD1(99,struct SignalSemaphore *,FindSemaphore,STRPTR name,A1)
  225.   return (struct SignalSemaphore *)FindName(&SysBase->SemaphoreList,name);
  226. }
  227.